package com.pi.common.utlis;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.concurrent.ConcurrentHashMap;

import static java.nio.file.StandardWatchEventKinds.*;

/**
 * 非spring容器下运行文件监控
 */
public class FileWatcher {

    private final Logger log = LoggerFactory.getLogger(FileWatcher.class);
    //路径
    private final Path directory;
    // 例如 "*.csv"
    private final String filePattern;

    private final ConcurrentHashMap<Path, Long> fileMaps = new ConcurrentHashMap<>();

    //构造函数初始一下
    public FileWatcher(String dirPath, String filePattern) {
        if (dirPath == null || dirPath.trim().isEmpty()) {
            throw new IllegalArgumentException("监控目录路径不能为空");
        }
        this.directory = Paths.get(dirPath);
        this.filePattern = filePattern;

        if (!Files.isDirectory(this.directory)) {
            throw new IllegalArgumentException("指定路径不是有效目录: " + dirPath);
        }
    }

    public void startWatching() throws Exception {
        try(WatchService watcher = FileSystems.getDefault().newWatchService()){
            directory.register(watcher, ENTRY_CREATE, ENTRY_MODIFY);

            log.info("开始监控目录:[{}]",directory);

            while (!Thread.currentThread().isInterrupted()) {
                WatchKey key;
                try {
                    key = watcher.take();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }

                for (WatchEvent<?> event : key.pollEvents()) {
                    if (event.kind() == OVERFLOW) continue;

                    Path filename = (Path) event.context();
                    if (filename.toString().matches(convertGlobToRegex(filePattern))) {
                        Path fullPath = directory.resolve(filename);
                        handleFile(fullPath);
                    }
                }

                if (!key.reset()) {
                    System.err.println("WatchKey已失效");
                    break;
                }

                // 定期清理旧的记录(避免内存泄漏)
                cleanUpProcessedRecords();
            }
        }


    }

    //处理文件逻辑
    private void handleFile(Path fullPath) throws IOException {
        long currentModified = Files.getLastModifiedTime(fullPath).toMillis();
        Long lastProcessed = fileMaps.get(fullPath);

        // 5秒内不重复处理同一文件
        if (lastProcessed != null && (currentModified - lastProcessed < 5000)) {
            return;
        }

        if (isFileReady(fullPath.toFile())) {
            log.info("发现匹配文件: [{}]", fullPath);
            log.info("文件大小: [{}",Files.size(fullPath) + "]bytes");
            log.info("最后修改时间:[{}] ",Files.getLastModifiedTime(fullPath));
            printFileContent(fullPath.toFile());
            fileMaps.put(fullPath, currentModified);
        }
    }

    private void cleanUpProcessedRecords() {
        long now = System.currentTimeMillis();
        fileMaps.entrySet().removeIf(entry ->
                (now - entry.getValue()) > 60000); // 清理1分钟前的记录
    }

    /**
     * 检查文件是否准备好被读取
     */
    private boolean isFileReady(File file) throws IOException {
        // 尝试获取文件锁
        try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
            return channel.tryLock(0, Long.MAX_VALUE, true) != null;
        } catch (Exception e) {
            return false;
        }
    }

    private void printFileContent(File file) {
        // 你的文件处理逻辑
        log.info("正在处理文件: {}",file.getName());

        log.info("====文件内容开始=====");

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {

            String line;
            int lineNumber = 1;
            while ((line = reader.readLine()) != null) {
                System.out.printf("%4d: %s%n", lineNumber++, line);
            }

        } catch (FileNotFoundException e) {
            log.error("文件不存在: " + e.getMessage());
        } catch (IOException e) {
            log.error("读取文件错误: " + e.getMessage());
        }

        log.info("文件内容读取完毕,文件名{}",file.getName());
    }

    private String convertGlobToRegex(String pattern) {
        return pattern.replace(".", "\\.").replace("*", ".*").replace("?", ".").replace("|", "\\|");
    }

    public static void main(String[] args) throws Exception {
        new FileWatcher("C:\\Users\\phyhunter\\Desktop\\0518_Boy", "我*.txt").startWatching();
    }
}
